#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//函数名其实代表了函数的入口地址
void func()
{
	printf("hello world!");
}

int func1(int a, char b)
{
	printf("func1");
	return a+b;
}

//如何去定义指向函数的指针
//决定函数类型应该是: 函数的返回值 函数的参数列表
void test01()
{
	//定义函数类型
	typedef int (FUNC_TYPE)(int, char);
	FUNC_TYPE *pFUNC = func1;
	pFUNC(10, 'a');

	//定义函数指针类型
	typedef int(*FUNC_P)(int,char);
	FUNC_P p = func1;
	p(20, 'b');

	//直接定义函数指针变量
	int (*p2)(int, char) = NULL;
	int (*p3)(int, char) = (int(*)(int, char))NULL;//把指针类型转换为函数指针类型
	p2 = func1;
	p2(30, 'c');
	printf("p2 size:%d\n", sizeof(p2));

	p3 = func1;
	p3(40, 'd');
}

int con1(int a, int b)
{
	return a + b;
}

int con2(int a, int b)
{
	return a + b + 10;
}

int con3(int a, int b)
{
	return a + b + 20;
}

void test02()
{
	int (*pFunc)(int,int) = con1;
	printf("%d\n", pFunc(10, 20));
	pFunc = con2;
	printf("%d\n", pFunc(10, 20));
	pFunc = con3;
	printf("%d\n", pFunc(10, 20));
}

//函数就可以作为另外一个函数的参数
void doLogic(int(*pFunc)(int,int))
{
	int a = 10;
	int b = 30;
	int ret = pFunc(a, b);
	printf("ret = %d\n", pFunc(a, b));
}

void test03()
{
	doLogic(con1);
	doLogic(con2);
	doLogic(con3);
}

//函数指针数组
void func11()
{
	printf("func1\n");
}
void func2()
{
	printf("func2\n");
}
void func3()
{
	printf("func3\n");
}
void test04()
{
	void (*funcArray[3])();
	funcArray[0] = func11;
	funcArray[1] = func2;
	funcArray[2] = func3;

	for(int i = 0; i< 3; ++i)
	{
		funcArray[i]();
	}
}


//函数指针做函数参数
void printAllArray(void *arr, int eleSize, int len, void (*print)(void *))
{
	char *start = (char *)arr;
	
	for(int i = 0; i < len; ++i)
	{
		print(start + i * eleSize);
	}
}

void MyPrint(void *data)
{
	int *p = (int *)data;
	printf("%d ", *p);
}

struct Person
{
	char name[64];
	int age;
};

void MyPersonPrint(void *person)
{
	struct Person *p = (struct Person *)person;
	printf("person name=%s, age=%d \n", p->name, p->age);
}

void test05()
{
	int arr[] = {1,2,3,4,5};
	printAllArray(arr, sizeof(int), 5, MyPrint);
	
	struct Person persons[] = {
		{"aaa", 10},
		{"bbb", 20},
		{"ccc", 30},
		{"ddd", 40},
		{"eee", 50},
	};

	printAllArray(persons, sizeof(struct Person), 5, MyPersonPrint);
}

int main(int argc, char const *argv[])
{
	printf("函数入口地址%p\n", func);
	
	//int *funcaddr = (int *)func;
	
	void (*pfunc)() = func;
	pfunc();

	//函数名其实就是函数地址
	

	test01();
	test02();
	test03();
	test04();
	test05();

	return 0;
}
